/**
 * Copyright ® 2006 Shenzhen Cogent Co.Ltd.
 * All right reserved.
 */
package com.cogent.common.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

/**
 * 
 * Date: 2006-3-17
 * Author: KKK
 */
public class XMLProperty {
	
	private static Logger _log = Logger.getLogger(XMLProperty.class);

    private File file;
    private Document doc;
    
    private Map propertyCache = new HashMap();

    /**
     * 传入XML文件，初始化对象
     * @param file xml文件
     */
    public XMLProperty(String file) {
        this.file = new File(file);
        try {
        	SAXBuilder builder = new SAXBuilder();
        	doc = builder.build(new File(file));
        } catch (Exception e) {
            _log.error("read xml:" + file, e);
        }
    }
    
    /**
     * 获取指定节点的值，
     * 不存在则返回null
     * @param name 节点
     * @return
     */
    public String getProperty(String name) {
    	if (name == null || name.trim().length() <= 0) {
    		return null;
    	}
        if (propertyCache.containsKey(name)) {
            return (String) propertyCache.get(name);
        }
        String[] propName = parsePropertyName(name);
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length; i++) {
            element = element.getChild(propName[i]);
            if (element == null) {
                return null;
            }
        }
        String value = element.getTextTrim();
        if (value == null || value.length() <= 0) {
            return null;
        } else {
            propertyCache.put(name, value);
            return value;
        }
    }
    
    /**
     * 获取指定节点的孩子
     * @param parent 父节点
     * @return
     */
    public String[] getChildProperty(String parent) {
        String[] propName = parsePropertyName(parent);
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length; i++) {
            element = element.getChild(propName[i]);
            if (element == null) {
                return new String[] {};
            }
        }
        List child = element.getChildren();
        String[] childNames = new String[child.size()];
        for (int i=0; i<child.size(); i++) {
            childNames[i] =  ( (Element) child.get(i) ).getName();
        }
        return childNames;
    }
    
    /**
     * 保存指定节点
     * @param name 节点
     * @param value 值
     */
    public void setProperty(String name, String value) {
        propertyCache.put(name, value);
        
        String[] propName = parsePropertyName(name);
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length; i++) {
            if (element.getChild(propName[i]) == null) {
            	element.addContent(new Element(propName[i]));
            } 
            element = element.getChild(propName[i]);
        }
        element.setText(value);
        saveProperty();
    }
    
    /**
     * 保存指定节点
     * @param name
     */
    public void deleteProperty(String name) {
        String[] propName = parsePropertyName(name);
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length - 1; i++) {
            element = element.getChild(propName[i]);
            if (element == null) {
                return;
            }
        }
        element.removeChild(propName[propName.length-1]);
        propertyCache.remove(name);
        saveProperty();
    }
    
    private String[] parsePropertyName(String name) {
        int size = 1;
        for (int i=0; i<name.length(); i++) {
            if (name.charAt(i) == '.') {
                size++;
            }
        }
        String[] propName = new String[size];
        StringTokenizer token = new StringTokenizer(name, ".");
        int i = 0;
        while (token.hasMoreTokens()) {
            propName[i] = token.nextToken();
            i++;
        }
        return propName;
    }
    
    private synchronized void saveProperty() {
        OutputStream out = null;
        boolean error = false;
        File tempFile = null;
        try {
            tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
            out = new BufferedOutputStream(new FileOutputStream(tempFile));
            XMLOutputter outputter = new XMLOutputter();
            outputter.output(doc, out);
        } catch (IOException e) {
            error = true;
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                error = true;
                e.printStackTrace();
            }
        }
        if (!error) {
            error = file.delete();
            error = tempFile.renameTo(file);
        }
    }
}
